home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / utl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  62.5 KB  |  2,023 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 42
  2. /*______________________________________________________________________
  3.  
  4.      utl.c - Utilities.
  5.     
  6.      Copyright © 1988, 1989, 1990 Northwestern University.    Permission is granted
  7.      to use this code in your own projects, provided you give credit to both
  8.      John Norstad and Northwestern University in your about box or document.
  9.     
  10.      This module exports miscellaneous reusable utility routines.
  11. _____________________________________________________________________*/
  12.  
  13.  
  14. #pragma load EUDORA_LOAD
  15.  
  16. #pragma segment utl
  17.  
  18. /*______________________________________________________________________
  19.  
  20.      Global Variables.
  21. _____________________________________________________________________*/
  22.  
  23.  
  24. static SysEnvRec         TheWorld;            /* system environment record */
  25. static Boolean             GotSysEnviron = false; 
  26.                                                                         /* true if sys environ has been
  27.                                                                              gotten */
  28.     
  29.                 
  30. static CursHandle      *CursArray;        /* ptr to array of cursor handles */
  31. static short                 NumCurs;             /* number of cursors to rotate */
  32. static short                 TickInterval;    /* number of ticks between rotations */
  33. static short                 CurCurs;             /* index of current cursor */
  34. static short                 LastTick;            /* tick count at loast rotation */
  35.  
  36. static ModalFilterProcPtr  Filter;    /* dialog filter proc */
  37. static short                 CancelItem;        /* item number of cancel button */
  38.  
  39. /*______________________________________________________________________
  40.  
  41.      GetSysEnvirons - Get System Environment.
  42.     
  43.      Exit:        global variable TheWorld = system environment record.
  44.                         global variable GotSysEnviron = true.
  45. _____________________________________________________________________*/
  46.  
  47.  
  48. static void GetSysEnvirons (void)
  49.  
  50. {
  51.      if (!GotSysEnviron) {
  52.             (void) SysEnvirons(curSysEnvVers, &TheWorld);
  53.             GotSysEnviron = true;
  54.      };
  55. }
  56.  
  57. /*______________________________________________________________________
  58.  
  59.      utl_AppendDITL - Append DITL to End of Dialog.
  60.     
  61.      Entry:     theDialog = pointer to dialog.
  62.                         theDITLID = rsrc id of DITL.
  63.                             
  64.      Exit:        function result = item number of first appended item.
  65.     
  66.      The dialog window is expanded to accomodate the new items, and the
  67.      new items are offset to appear at the bottom of the dialog.
  68.     
  69.      This routine is particularly useful for appending items to the
  70.      standard Page Setup and Print Job dialogs.  (See TN 95).  It was
  71.      written by Lew Rollins of Apple's Human-Systems Interface Group,
  72.      in MPW Pascal.  I translated it to MPW C.
  73.     
  74.      The only significant difference between this routine and Rollin's
  75.      version is that this version does not release the DITL resource.
  76. _____________________________________________________________________*/
  77.  
  78.  
  79. short utl_AppendDITL (DialogPtr theDialog, short theDITLID)
  80.  
  81. {
  82.      typedef struct DITLItem {
  83.             Handle                 itmHndl;                  /* handle or proc ptr */
  84.             Rect                     itmRect;                  /* display rect */
  85.             char                     itmType;                  /* item type */
  86.             unsigned char  itmData;                  /* item data length byte */
  87.      } DITLItem;
  88.     
  89.      typedef struct itemList {
  90.             short                  dlgMaxIndex;          /* num items - 1 */
  91.             DITLItem             DITLItems[1];         /* array of DITL items */
  92.      } itemList;
  93.     
  94.      short                    offset;              /* item offset */
  95.      Rect                     maxRect;             /* max dialog rect size so far */
  96.      Handle                 hDITL;                 /* handle to DITL */
  97.      DITLItem             *pItem;              /* pointer to item being appended */
  98.      itemList             **hItems;          /* handle to DLOG's item list */
  99.      short                    sizeDITL;          /* size of DLOG's item list */
  100.      short                    firstItem;         /* item num of first appended item */
  101.      short                    newItems;          /* number of new items */
  102.      short                    dataSize;          /* size of data for current item */
  103.      short                    i;                         /* loop index */
  104.     
  105.      /* Initialize. */
  106.     
  107.      maxRect = theDialog->portRect;
  108.      offset = maxRect.bottom;
  109.      maxRect.bottom -= 5;
  110.      maxRect.right -= 5;
  111.      hItems = (itemList**)(((DialogPeek)theDialog)->items);
  112.      sizeDITL = GetHandleSize((Handle)hItems);
  113.      firstItem = (**hItems).dlgMaxIndex + 2;
  114.      hDITL = GetResource('DITL', theDITLID);
  115.      HLock(hDITL);
  116.      newItems = **(short**)hDITL + 1;
  117.      PtrAndHand(*hDITL+2, (Handle)hItems,
  118.             GetHandleSize(hDITL)-2);
  119.      (**hItems).dlgMaxIndex += newItems;
  120.      HUnlock(hDITL);
  121.      HLock((Handle)hItems);
  122.      (char*)pItem = (char*)(*hItems) + sizeDITL;
  123.     
  124.      /* Main loop.    Add each item to dialog item list. */
  125.     
  126.      for (i = 1; i <= newItems; i++) {
  127.             OffsetRect(&pItem->itmRect, 0, offset);
  128.             UnionRect(&pItem->itmRect, &maxRect, &maxRect);
  129.             switch (pItem->itmType & 0x7f) {
  130.                  case ctrlItem+btnCtrl:
  131.                  case ctrlItem+chkCtrl:
  132.                  case ctrlItem+radCtrl:
  133.                         pItem->itmHndl = (Handle)NewControl(theDialog,
  134.                              &pItem->itmRect, &pItem->itmData, true, 0, 0, 1, 
  135.                              pItem->itmType & 0x03, 0);
  136.                         break;
  137.                  case ctrlItem+resCtrl:
  138.                         pItem->itmHndl = (Handle)GetNewControl(
  139.                              *(short*)(&pItem->itmData+1),
  140.                              theDialog);
  141.                         (**((ControlHandle)(pItem->itmHndl))).contrlRect =
  142.                              pItem->itmRect;
  143.                         break;
  144.                  case statText:
  145.                  case editText:
  146.                         PtrToHand(&pItem->itmData+1, (Handle *)&(pItem->itmHndl), 
  147.                              pItem->itmData);
  148.                         break;
  149.                  case iconItem:
  150.                         pItem->itmHndl = GetIcon(*(short*)(&pItem->itmData+1));
  151.                         break;
  152.                  default:
  153.                         pItem->itmHndl = nil;
  154.             };
  155.             dataSize = (pItem->itmData + 1) & 0xfffe;
  156.             (char*)pItem += dataSize + sizeof(DITLItem);
  157.      };
  158.     
  159.      /* Finish up. */
  160.     
  161.      HUnlock((Handle)hItems);
  162.      maxRect.bottom += 5;
  163.      maxRect.right += 5;
  164.      SizeWindow(theDialog, maxRect.right, maxRect.bottom, true);
  165.      return firstItem;
  166. }
  167.  
  168. /*______________________________________________________________________
  169.  
  170.      utl_CenterDlogRect - Center a dialog rectangle.
  171.     
  172.      Entry:     rect = rectangle.
  173.                         centerMain = true to center on main (menu bar) screen.
  174.                         centerMain = false to center on the screen containing
  175.                              the maximum intersection with the frontmost window.
  176.     
  177.      Exit:        rect = rectangle offset so that it is centered on
  178.                              the specified screen, with twice as much space below
  179.                              the rect as above.
  180.                             
  181.      See HIN 6.
  182. _____________________________________________________________________*/
  183.  
  184.  
  185. void utl_CenterDlogRect (Rect *rect, Boolean centerMain)
  186.  
  187. {
  188.      Rect         screenRect;             /* screen rectangle */
  189.      short        mBHeight;                 /* menu bar height */
  190.      GDHandle gd;                             /* gdevice */
  191.      Rect         windRect;                 /* window rectangle */
  192.      Boolean    hasMB;                        /* true if screen contains menu bar */
  193.  
  194.      mBHeight = utl_GetMBarHeight();
  195.      if (centerMain) {
  196.             screenRect = qd.screenBits.bounds;
  197.      } else {
  198.             utl_GetWindGD(FrontWindow(), &gd, &screenRect, &windRect, &hasMB);
  199.             if (!hasMB) mBHeight = 0;
  200.      };
  201.      OffsetRect(rect,
  202.             (screenRect.right + screenRect.left - rect->right - rect->left) >> 1,
  203.             (screenRect.bottom + ((screenRect.top + mBHeight - rect->top)<<1) - 
  204.                  rect->bottom + 7) / 3);
  205. }
  206.  
  207. /*______________________________________________________________________
  208.  
  209.      utl_CenterRect - Center a rectangle on the main screen.
  210.     
  211.      Entry:     rect = rectangle.
  212.     
  213.      Exit:        rect = rectangle offset so that it is centered on
  214.                              the main screen.
  215. _____________________________________________________________________*/
  216.  
  217.  
  218. void utl_CenterRect (Rect *rect)
  219.  
  220. {
  221.      Rect         screenRect;             /* main screen rectangle */
  222.      short        mBHeight;                 /* menu bar height */
  223.  
  224.      mBHeight = utl_GetMBarHeight();
  225.      screenRect = qd.screenBits.bounds;
  226.      OffsetRect(rect,
  227.             (screenRect.right + screenRect.left - rect->right - rect->left) >> 1,
  228.             (screenRect.bottom - screenRect.top + mBHeight -
  229.                  rect->bottom - rect->top) >> 1);
  230. }
  231.  
  232. /*______________________________________________________________________
  233.  
  234.      utl_CheckPack - Check to see if a package exists.
  235.     
  236.      Entry:     packNum = package number.
  237.                         preload = true to preload package.
  238.                             
  239.      Exit:        function result = true if package exists.
  240. _____________________________________________________________________*/
  241.  
  242.  
  243. Boolean utl_CheckPack (short packNum, Boolean preload)
  244.  
  245. {
  246.      short             trapNum;             /* trap number */
  247.      Handle          h;                         /* handle to PACK resource */
  248.     
  249.      /* Check to make sure the trap exists, by comparing its trap address to
  250.             the trap address of the unimplemented trap. */
  251.     
  252.      trapNum = packNum + 0x1e7;
  253.      if (NGetTrapAddress(trapNum & 0x3ff, ToolTrap) ==
  254.             NGetTrapAddress(_Unimplemented & 0x3ff, ToolTrap)) return false;
  255.             
  256.      /* Check to make sure the package exists on the System file or in
  257.             ROM.    If it's not in ROM make it nonpurgeable, if requested. */
  258.     
  259.      if (preload) {
  260.             if (utl_Rom64()) {
  261.                  h = GetResource('PACK', packNum);
  262.                  if (!h) return false;
  263.                  HNoPurge(h);
  264.             } else {
  265.                  *(unsigned short*)RomMapInsert = 0xFF00;
  266.                  h = GetResource('PACK', packNum);
  267.                  if (!h) return false;
  268.                  if ((*(unsigned long*)h & 0x00FFFFFF) <
  269.                         *(unsigned long*)ROMBase) {
  270.                         h = GetResource('PACK', packNum);
  271.                         HNoPurge(h);
  272.                  };
  273.             };
  274.             return true;
  275.      } else {
  276.             SetResLoad(false);
  277.             if (!utl_Rom64()) *(unsigned short*)RomMapInsert = 0xFF00;
  278.             h = GetResource('PACK', packNum);
  279.             SetResLoad(true);
  280.             if (h) return true; else return false;
  281.      };
  282. }
  283.  
  284. /*______________________________________________________________________
  285.  
  286.      utl_CopyPString - Copy Pascal String.
  287.     
  288.      Entry:     dest = destination string.
  289.                         source = source string.
  290. _____________________________________________________________________*/
  291.  
  292.  
  293. void utl_CopyPString (Str255 dest, Str255 source)
  294.  
  295. {
  296.      memcpy(dest, source, *source+1);
  297. }
  298.  
  299. /*______________________________________________________________________
  300.  
  301.      utl_CouldDrag - Determine if a window could be dragged to a location.
  302.     
  303.      Entry:     windRect = window rectangle, in global coords.
  304.                         offset = pixel offset used in DragRect calls.
  305.     
  306.      Exit:        function result = true if the window could have been
  307.                              dragged to the specified position.
  308.                             
  309.      This routine is used when restoring windows to saved positions.    According
  310.      to HIN 6, we must check to see if the window "could have been dragged to
  311.      the saved position."
  312.     
  313.      The "offset" parameter is usually 4.  When initializing the boundary rectangle
  314.      for DragWindow calls, normally the boundary rectangle of the desktop gray
  315.      region is inset by 4 pixels.  If some value other than 4 is used, it should
  316.      be passed to CouldDrag as the "offset" parameter.
  317.     
  318.      The algorithm used is the following:  The routine computes the four squares
  319.      at the corners of the title bar.  "true" is returned if and only if at least one 
  320.      of these four squares is completely contained within the desktop gray region.
  321.     
  322.      Three pixels are added to the offset to err on the side of requiring a larger
  323.      portion of the drag bar to be visible. 
  324. _____________________________________________________________________*/
  325.  
  326.  
  327. Boolean utl_CouldDrag (Rect *windRect, short offset)
  328.  
  329. {
  330.      RgnHandle                 rgn;              /* scratch region handle */
  331.      Boolean                     could;          /* function result */
  332.      short                         corner;         /* which corner */
  333.      Rect                          r;                  /* corner rectangle */
  334.  
  335.      rgn = NewRgn();
  336.      could = false;
  337.      offset += 3;
  338.      for (corner = 1; corner <= 4; corner++) {
  339.             switch (corner) {
  340.                  case 1:
  341.                         r.top = windRect->top - titleBarHeight;
  342.                         r.left = windRect->left;
  343.                         break;
  344.                  case 2:
  345.                         r.top = windRect->top - offset;
  346.                         r.left = windRect->left;
  347.                         break;
  348.                  case 3:
  349.                         r.top = windRect->top - titleBarHeight;
  350.                         r.left = windRect->right - offset;
  351.                         break;
  352.                  case 4:
  353.                         r.top = windRect->top - offset;
  354.                         r.left = windRect->right - offset;
  355.                         break;
  356.             };
  357.             r.bottom = r.top + offset;
  358.             r.right = r.left + offset;
  359.             RectRgn(rgn, &r);
  360.             DiffRgn(rgn, *(RgnHandle*)GrayRgn, rgn);
  361.             if (EmptyRgn(rgn)) {
  362.                  could = true;
  363.                  break;
  364.             };
  365.      };
  366.      DisposeRgn(rgn);
  367.      return could;
  368. }
  369.  
  370. /*______________________________________________________________________
  371.  
  372.      utl_DILoad - Load Disk Initialization Package.
  373.     
  374.      Exit:        Disk initialization package loaded.
  375.                         
  376.      This routine is identical to the DILoad routine (see IM II-396),
  377.      except that it closes any resource files opened by the routine.    This is
  378.      necessary to undo a bug in the DaynaFile software.  DaynaFile patches
  379.      DILoad.    The patch opens a resource file without closing it.  The
  380.      effect on Disinfectant if we don't do anything about this is that 
  381.      the DaynaFile icon is displayed in Disinfectant's main window instead of
  382.      Disinfectant's icon.  
  383. _____________________________________________________________________*/
  384.  
  385.  
  386. void utl_DILoad (void)
  387.  
  388. {
  389.      short             curResFile;             /* ref num of current resource file
  390.                                                                         before calling DILoad */
  391.      short             topResFile;             /* ref num of top resource file
  392.                                                                         after calling DILoad */
  393.     
  394.      curResFile = CurResFile();
  395.      DILoad();
  396.      while ((topResFile = CurResFile()) != curResFile) CloseResFile(topResFile);
  397. }
  398.  
  399. /*______________________________________________________________________
  400.  
  401.      utl_DoDiskInsert - Handle a disk inserted event.
  402.     
  403.      Entry:     message = message field from disk insertion event record
  404.                              = 16/MountVol return code, 16/drive number.
  405.     
  406.      Exit:        vRefNum = vol ref num of inserted volume.
  407.                         function result = error code.
  408.     
  409.      If MountVol returned an error code, the disk initialization package
  410.      is called to initialize the disk.
  411. _____________________________________________________________________*/
  412.  
  413.  
  414. OSErr utl_DoDiskInsert (long message, short *vRefNum)
  415.  
  416. {
  417.      OSErr                    rCode;                        /* result code */
  418.      short                    driveNum;                 /* drive number */
  419.      HParamBlockRec pBlock;                     /* vol info param block */
  420.      Handle                 dlgHandle;                /* handle to disk init dialog */
  421.      Rect                     dlgRect;                    /* disk init dialog rectangle */
  422.      Point                    where;                        /* location of disk init dialog */
  423.      short                    curVol;                     /* index in VCB queue */
  424.     
  425.      /* Get result code and drive number from event message. */
  426.     
  427.      rCode = (message >> 16) & 0xffff;
  428.      driveNum = message & 0xffff;
  429.     
  430.      /* If the result code indicates an error, call DIBadMount to initialize
  431.             the disk. */
  432.             
  433.      if (rCode) {
  434.             
  435.             /* Center the disk initialization package dialog. */
  436.             
  437.             DILoad();
  438.             dlgHandle = GetResource('DLOG', -6047);
  439.             dlgRect = **(Rect**)dlgHandle;
  440.             utl_CenterDlogRect(&dlgRect, false);
  441.             SetPt(&where, dlgRect.left, dlgRect.top);
  442.             
  443.             /* Call DIBadMount. */
  444.             
  445.             if (rCode = DIBadMount(where, message)) return rCode;
  446.             
  447.      };
  448.     
  449.      /* Search mounted volumes to find inserted one. */
  450.     
  451.      pBlock.volumeParam.ioNamePtr = nil;
  452.      curVol = 0;
  453.      while (true) {
  454.             pBlock.volumeParam.ioVolIndex = ++curVol;
  455.             pBlock.volumeParam.ioVRefNum = 0;
  456.             if (rCode = PBHGetVInfo(&pBlock, false)) return rCode;
  457.             if (pBlock.volumeParam.ioVDrvInfo == driveNum) break;
  458.      };
  459.      *vRefNum = pBlock.volumeParam.ioVRefNum;
  460.      return noErr;
  461.  
  462. /*______________________________________________________________________
  463.  
  464.      utl_DrawGrowIcon - Draw Grow Icon.
  465.     
  466.      Entry:                 theWindow = pointer to window.
  467.     
  468.      This routine is identical to the Window Manager routine
  469.      DrawGrowIcon, except that it does not draw the lines enclosing the
  470.      scroll bars.
  471. _____________________________________________________________________*/
  472.  
  473.  
  474. void utl_DrawGrowIcon (WindowPtr theWindow) 
  475.  
  476. {
  477.      RgnHandle                 clipRgn;             /* saved clip region */
  478.      Rect                          clipRect;            /* clip rectangle */
  479.     
  480.      clipRgn = NewRgn();
  481.      GetClip(clipRgn);
  482.      clipRect = theWindow->portRect;
  483.      clipRect.left = clipRect.right - 15;
  484.      clipRect.top = clipRect.bottom - 15;
  485.      ClipRect(&clipRect);
  486.      DrawGrowIcon(theWindow);
  487.      SetClip(clipRgn);
  488.      DisposeRgn(clipRgn);
  489. }
  490.  
  491. /*______________________________________________________________________
  492.  
  493.      utl_Ejectable - Test for ejectable volume.
  494.     
  495.      Entry:     vRefNum = volume reference number.
  496.     
  497.      Exit:        function result = true if volume is on an ejectable drive.
  498. _____________________________________________________________________*/
  499.  
  500.  
  501. Boolean utl_Ejectable (short vRefNum)
  502.     
  503. {
  504.      HParamBlockRec pBlock;                     /* vol info param block */
  505.      short                    driveNum;                 /* driver number of cur vol */
  506.      DrvQEl                 *curDrive;                /* ptr to current drive queue element */
  507.      OSErr                    rCode;                        /* result code */
  508.      unsigned char    flagByte;                 /* drive queue element flag byte */
  509.     
  510.      /* Get driveNum = drive number of drive containing volume. */
  511.     
  512.      pBlock.volumeParam.ioNamePtr = nil;
  513.      pBlock.volumeParam.ioVolIndex = 0;
  514.      pBlock.volumeParam.ioVRefNum = vRefNum;;
  515.      if (rCode = PBHGetVInfo(&pBlock, false)) return false;
  516.      driveNum = pBlock.volumeParam.ioVDrvInfo;
  517.     
  518.      /* Walk the drive queue until we find driveNum.    The second byte in
  519.             the four flag bytes preceding the drive queue element is 8 or $48 
  520.             if the drive is nonejectable. */
  521.     
  522.      curDrive = (DrvQEl*)(GetDrvQHdr())->qHead;
  523.      while (true) {
  524.             if (curDrive->dQDrive == driveNum) {
  525.                  flagByte = *((Ptr)curDrive - 3);
  526.                  return (flagByte != 8 && flagByte != 0x48);
  527.             };
  528.             curDrive = (DrvQEl*)curDrive->qLink;
  529.             if (!curDrive) return false;
  530.      };
  531. }
  532.  
  533. /*______________________________________________________________________
  534.  
  535.      utl_FixStdFile - Fix Standard File Pacakge.
  536.     
  537.      This routine should be called before calling the Standard File 
  538.      package if there's any chance that SFSaveDisk might specify
  539.      a volume that has been umounted.  Standard File gets confused if this
  540.      happens and presents an alert telling the user that a "system error"
  541.      has occurred.
  542.     
  543.      This routine checks to make sure that SFSaveDisk specifies a volume
  544.      that is still mounted.  If not, it sets it to the first mounted
  545.      volume, and it sets CurDirStore to the root directory on that volume.
  546. _____________________________________________________________________*/
  547.                             
  548.                             
  549. void utl_FixStdFile (void)
  550.  
  551. {
  552.      ParamBlockRec    vBlock;              /* vol info param block */
  553.                                                                         
  554.      vBlock.volumeParam.ioNamePtr = nil;
  555.      vBlock.volumeParam.ioVRefNum = -*(short*)SFSaveDisk;
  556.      vBlock.volumeParam.ioVolIndex = 0;
  557.      if (PBGetVInfo(&vBlock, false)) {
  558.             vBlock.volumeParam.ioVolIndex = 1;
  559.             (void) PBGetVInfo(&vBlock, false);
  560.             *(short*)SFSaveDisk = -vBlock.volumeParam.ioVRefNum;
  561.             if (*(short*)FSFCBLen > 0) *(long*)CurDirStore = fsRtDirID;
  562.      };
  563. }
  564.  
  565. /*______________________________________________________________________
  566.  
  567.      utl_FlashButton - Flash Dialog Button.
  568.     
  569.      Entry:     theDialog = pointer to dialog.
  570.                         itemNo = item number of button to flash.
  571.                         
  572.      The push button is inverted for 8 ticks.  See HIN #10.
  573. _____________________________________________________________________*/
  574.  
  575.  
  576. void utl_FlashButton (DialogPtr theDialog, short itemNo)
  577.  
  578. {
  579.      short             itemType;                 /* item type */
  580.      Handle          item;                         /* item handle */
  581.      Rect              box;                          /* item rectangle */
  582.      short             roundFactor;          /* rounded corner factor for InvertRoundRect */
  583.      long              tickEnd;                  /* tick count to end flash */
  584.     
  585.      GetDItem(theDialog, itemNo, &itemType, &item, &box);
  586.      SetPort(theDialog);
  587.      roundFactor = (box.bottom - box.top)>>1;
  588.      InvertRoundRect(&box, roundFactor, roundFactor);
  589.      tickEnd = TickCount() + 8;
  590.      while (TickCount() < tickEnd);
  591.      InvertRoundRect(&box, roundFactor, roundFactor);
  592. }
  593.  
  594. /*______________________________________________________________________
  595.  
  596.      utl_FrameItem
  597.     
  598.      Entry:     theWindow = pointer to dialog window.
  599.                         itemNo = dialog item number.
  600.     
  601.      Exit:        dialog item rectangle framed.
  602.                         
  603.      This function is for use as a Dialog Manager user item procedure.
  604.      It is particularly useful for drawing rules (straight lines).    Simply
  605.      define the user item rectangle with bottom=top+1 or right=left+1.
  606. _____________________________________________________________________*/
  607.  
  608.  
  609. pascal void utl_FrameItem (WindowPtr theWindow, short itemNo)
  610.  
  611. {
  612.      short             itemType;                 /* item type */
  613.      Handle          item;                         /* item handle */
  614.      Rect              box;                          /* item rectangle */
  615.  
  616.      GetDItem(theWindow, itemNo, &itemType, &item, &box);
  617.      FrameRect(&box);
  618. }
  619.  
  620. /*______________________________________________________________________
  621.  
  622.      utl_GetApplVol - Get the volume reference number of the application volume.
  623.     
  624.      Exit:        function result = volume reference number of the volume 
  625.                              containing the current application.
  626. _____________________________________________________________________*/
  627.  
  628.  
  629. short utl_GetApplVol (void)
  630.  
  631. {
  632.      short             vRefNum;                  /* vol ref num */
  633.  
  634.      GetVRefNum(*(short*)(CurMap), &vRefNum);
  635.      return vRefNum;
  636. }
  637.  
  638. /*______________________________________________________________________
  639.  
  640.      utl_GetBlessedWDRefNum - Get the working directory reference number of
  641.             the Blessed Folder.
  642.     
  643.     
  644.      Exit:        function result = wdRefNum of blessed folder
  645. _____________________________________________________________________*/
  646.  
  647.  
  648. short utl_GetBlessedWDRefNum (void)
  649.  
  650. {
  651.      if (!GotSysEnviron) GetSysEnvirons();
  652.      return TheWorld.sysVRefNum;
  653. }
  654.  
  655. /*______________________________________________________________________
  656.  
  657.      utl_GetFontNumber - Get Font Number.
  658.     
  659.      Entry:     fontName = font name.
  660.     
  661.      Exit:        function result = true if font exists.
  662.                         fontNum = font number.
  663.                         
  664.      Copied from TN 191.
  665. _____________________________________________________________________*/
  666.  
  667.  
  668. Boolean utl_GetFontNumber (Str255 fontName, short *fontNum)
  669.  
  670. {
  671.      Str255          systemFontName;
  672.     
  673.      GetFNum(fontName, fontNum);
  674.      if (*fontNum) {
  675.             return true;
  676.      } else {
  677.             GetFontName(0, systemFontName);
  678.             return EqualString(fontName, systemFontName, false, false);
  679.      };
  680. }
  681.  
  682. /*______________________________________________________________________
  683.  
  684.      utl_GetLongSleep - Get Long Sleep Time.
  685.     
  686.      Exit:             function result = long sleep time.
  687.     
  688.      Returns the largest positive long integer (0x7fffffff) if the
  689.      system version is > 0x04ff, else returns 50.  See TN 177.
  690. _____________________________________________________________________*/
  691.  
  692.  
  693. long utl_GetLongSleep (void)
  694.  
  695. {
  696.      if (!GotSysEnviron) GetSysEnvirons();
  697.      return (TheWorld.systemVersion > 0x04ff) ? 0x7fffffff : 50;
  698. }
  699.  
  700. /*______________________________________________________________________
  701.  
  702.      utl_GetMBarHeight - Get Menu Bar Height
  703.     
  704.      Exit:        function result = menu bar height.
  705.     
  706.      See TN 117.
  707. _____________________________________________________________________*/
  708.  
  709.  
  710. short utl_GetMBarHeight (void)
  711.  
  712. {
  713.      static short          mBHeight = 0;
  714.     
  715.      if (!mBHeight) {
  716.             mBHeight = utl_Rom64() ? 20 : *(short*)MBarHeight;
  717.      };
  718.      return mBHeight;
  719. }
  720.  
  721. /*______________________________________________________________________
  722.  
  723.      utl_GetNewControl - Get New Control.
  724.     
  725.      Entry:     controlID = resource id of CNTL resource.
  726.                         theWindow = pointer to window record.
  727.                         
  728.      Exit:        function result = handle to new control record.
  729.                         
  730.      This routine is identical to the Control Manager routine GetNewControl,
  731.      except it does not release or make purgeable the CNTL resource.
  732. _____________________________________________________________________*/
  733.  
  734.  
  735. ControlHandle utl_GetNewControl (short controlID, 
  736.      WindowPtr theWindow)
  737.     
  738. {
  739.      Rect              boundsRect;             /* boundary rectangle */
  740.      short             value;                      /* initial control value */
  741.      Boolean         visible;                  /* true if visible */
  742.      short             max;                          /* max control value */
  743.      short             min;                          /* min control value */
  744.      short             procID;                     /* window proc id */
  745.      long              refCon;                     /* refCon field for window record */
  746.      Str255          title;                      /* window title */
  747.      Handle          theRez;                     /* handle to CNTL resource */
  748.     
  749.      theRez = GetResource('CNTL', controlID);
  750.      boundsRect = *(Rect*)(*theRez);
  751.      value = *(short*)(*theRez+8);
  752.      visible = *(Boolean*)(*theRez+10);
  753.      max = *(short*)(*theRez+12);
  754.      min = *(short*)(*theRez+14);
  755.      procID = *(short*)(*theRez+16);
  756.      refCon = *(long*)(*theRez+18);
  757.      utl_CopyPString(title, *theRez+22);
  758.      return NewControl(theWindow, &boundsRect, title, visible, value,
  759.             min, max, procID, refCon);
  760. }
  761.  
  762. /*______________________________________________________________________
  763.  
  764.      utl_GetNewDialog - Get New Dialog.
  765.     
  766.      Entry:     dialogID = resource id of DLOG resource.
  767.                         dStorage = pointer to dialog record.
  768.                         behind = window to insert in back of.
  769.                         
  770.      Exit:        function result = pointer to new dialog record.
  771.                         
  772.      This routine is identical to the Dialog Manager routine GetNewDialog,
  773.      except it does not release or make purgeable the DLOG resource.
  774. _____________________________________________________________________*/
  775.  
  776.  
  777. DialogPtr utl_GetNewDialog (short dialogID, Ptr dStorage, 
  778.      WindowPtr behind)
  779.     
  780. {
  781.      Rect              boundsRect;             /* boundary rectangle */
  782.      short             procID;                     /* window proc id */
  783.      Boolean         visible;                  /* true if visible */
  784.      Boolean         goAwayFlag;             /* true if window has go away box */
  785.      long              refCon;                     /* refCon field for window record */
  786.      Str255          title;                      /* window title */
  787.      Handle          theRez;                     /* handle to DLOG resource */
  788.      short             itemID;                     /* rsrc id of item list */
  789.      Handle          items;                      /* handle to item list */
  790.     
  791.      theRez = GetResource('DLOG', dialogID);
  792.      boundsRect = *(Rect*)(*theRez);
  793.      procID = *(short*)(*theRez+8);
  794.      visible = *(Boolean*)(*theRez+10);
  795.      goAwayFlag = *(Boolean*)(*theRez+12);
  796.      refCon = *(long*)(*theRez+14);
  797.      itemID = *(short*)(*theRez+18);
  798.      utl_CopyPString(title, *theRez+20);
  799.      items = GetResource('DITL', itemID);
  800.      return NewDialog(dStorage, &boundsRect, title, visible, procID, behind,
  801.             goAwayFlag, refCon, items);
  802. }
  803.  
  804. /*______________________________________________________________________
  805.  
  806.      utl_GetNewWindow - Get New Window.
  807.     
  808.      Entry:     windowID = resource id of WIND resource.
  809.                         wStorage = pointer to window record.
  810.                         behind = window to insert in back of.
  811.                         
  812.      Exit:        function result = pointer to new window record.
  813.                         
  814.      This routine is identical to the Window Manager routine GetNewWindow,
  815.      except it does not release or make purgeable the WIND resource.
  816. _____________________________________________________________________*/
  817.  
  818.  
  819. WindowPtr utl_GetNewWindow (short windowID, Ptr wStorage, 
  820.      WindowPtr behind)
  821.     
  822. {
  823.      Rect              boundsRect;             /* boundary rectangle */
  824.      short             procID;                     /* window proc id */
  825.      Boolean         visible;                  /* true if visible */
  826.      Boolean         goAwayFlag;             /* true if window has go away box */
  827.      long              refCon;                     /* refCon field for window record */
  828.      Str255          title;                      /* window title */
  829.      Handle          theRez;                     /* handle to WIND resource */
  830.     
  831.      theRez = GetResource('WIND', windowID);
  832.      boundsRect = *(Rect*)(*theRez);
  833.      procID = *(short*)(*theRez+8);
  834.      visible = *(Boolean*)(*theRez+10);
  835.      goAwayFlag = *(Boolean*)(*theRez+12);
  836.      refCon = *(long*)(*theRez+14);
  837.      utl_CopyPString(title, *theRez+18);
  838.      return NewWindow(wStorage, &boundsRect, title, visible, procID, behind,
  839.             goAwayFlag, refCon);
  840. }
  841.  
  842. /*______________________________________________________________________
  843.  
  844.      utl_GetSysVol - Get the volume reference number of the system volume.
  845.     
  846.      Exit:        function result = volume reference number of the volume 
  847.                              containing the currently active system file.
  848. _____________________________________________________________________*/
  849.  
  850.  
  851. short utl_GetSysVol (void)
  852.  
  853. {
  854.     
  855.      short             vRefNum;                  /* vol ref num */
  856.  
  857.      GetVRefNum(*(short*)(SysMap), &vRefNum);
  858.      return vRefNum;
  859. }
  860.  
  861. /*______________________________________________________________________
  862.  
  863.      utl_GetSysWD - Get WDRefNum of Blessed Folder.
  864.     
  865.      Exit:        function result = WDRefNum of Blessed Folder.
  866. _____________________________________________________________________*/
  867.  
  868.  
  869. short utl_GetSysWD (void)
  870.  
  871. {
  872.      if (!GotSysEnviron) GetSysEnvirons();
  873.      return TheWorld.sysVRefNum;
  874. }
  875.  
  876. /*______________________________________________________________________
  877.  
  878.      utl_GetWindGD - Get the GDevice containing a window.
  879.     
  880.      Entry:     theWindow = pointer to window.
  881.     
  882.      Exit:        gd = handle to GDevice, or nil if no color QD.
  883.                         screenRect = bounding rectangle of GDevice, or
  884.                              qd.screenBits.bounds if no color QD.
  885.                         windRect = content rectangle of window, in global
  886.                              coords.
  887.                         hasMB = true if this screen contains the menu bar.
  888.                         
  889.      The routine determines the GDevice (screen) containing the maximum
  890.      intersection with a window.    See TN 79.
  891. _____________________________________________________________________*/
  892.  
  893.  
  894. void utl_GetWindGD (WindowPtr theWindow, GDHandle *gd,
  895.      Rect *screenRect, Rect *windRect, Boolean *hasMB)
  896.     
  897. {
  898.      GrafPtr                savePort;                 /* saved grafport */
  899.      Rect                     sectRect;                 /* intersection rect */
  900.      GDHandle             curDevice;                /* current GDevice */
  901.      GDHandle             dominantDevice;     /* dominant GDevice */
  902.      long                     sectArea;                 /* intersection area */
  903.      long                     maxArea;                    /* max intersection area */
  904.     
  905.      *windRect = theWindow->portRect;
  906.      GetPort(&savePort);
  907.      SetPort(theWindow);
  908.      LocalToGlobal((Point*)&windRect->top);
  909.      LocalToGlobal((Point*)&windRect->bottom);
  910.      if (utl_HaveColor()) {
  911.             windRect->top -= titleBarHeight;
  912.             curDevice = GetDeviceList();
  913.             maxArea = 0;
  914.             dominantDevice = nil;
  915.             while (curDevice) {
  916.                  if (TestDeviceAttribute(curDevice, screenDevice) &&
  917.                         TestDeviceAttribute(curDevice, screenActive)) {
  918.                         SectRect(windRect, &(**curDevice).gdRect, §Rect);
  919.                         sectArea = (long)(sectRect.right - sectRect.left) * 
  920.                              (long)(sectRect.bottom - sectRect.top);
  921.                         if (sectArea > maxArea) {
  922.                              maxArea = sectArea;
  923.                              dominantDevice = curDevice;
  924.                         };
  925.                  };
  926.                  curDevice = GetNextDevice(curDevice);
  927.             };
  928.             windRect->top += titleBarHeight;
  929.             if (dominantDevice) {
  930.                  *gd = dominantDevice;
  931.                  *screenRect = (**dominantDevice).gdRect;
  932.                  *hasMB = dominantDevice == GetMainDevice();
  933.             } else {
  934.                  *gd = nil;
  935.                  *screenRect = qd.screenBits.bounds;
  936.                  *hasMB = true;
  937.             };
  938.      } else {
  939.             *gd = nil;
  940.             *screenRect = qd.screenBits.bounds;
  941.             *hasMB = true;
  942.      };
  943.      SetPort(savePort);
  944. }
  945.  
  946. /*______________________________________________________________________
  947.  
  948.      utl_GetIndGD - Get the nth GDevice.
  949.     
  950.      Entry:     n = device index.
  951.     
  952.      Exit:        gd = handle to GDevice, or nil if no color QD.
  953.                         screenRect = bounding rectangle of GDevice, or
  954.                              qd.screenBits.bounds if no color QD.
  955.                         hasMB = true if this screen contains the menu bar.
  956.  
  957. _____________________________________________________________________*/
  958.  
  959.  
  960. void utl_GetIndGD (short n,GDHandle *gd, Rect *screenRect, Boolean *hasMB)
  961.     
  962. {
  963.      GDHandle             curDevice;                /* current GDevice */
  964.      GDHandle             dominantDevice;     /* dominant GDevice */
  965.     
  966.      if (utl_HaveColor()) {
  967.             dominantDevice = nil;
  968.             curDevice = GetDeviceList();
  969.             while (curDevice && n--) {
  970.                  if (TestDeviceAttribute(curDevice, screenDevice) &&
  971.                         TestDeviceAttribute(curDevice, screenActive))
  972.                              dominantDevice = curDevice;
  973.                  curDevice = GetNextDevice(curDevice);
  974.             }
  975.             if (dominantDevice) {
  976.                  *gd = dominantDevice;
  977.                  *screenRect = (**dominantDevice).gdRect;
  978.                  *hasMB = dominantDevice == GetMainDevice();
  979.             } else {
  980.                  *gd = nil;
  981.                  *screenRect = qd.screenBits.bounds;
  982.                  *hasMB = true;
  983.             };
  984.      } else {
  985.             *gd = nil;
  986.             *screenRect = qd.screenBits.bounds;
  987.             *hasMB = true;
  988.      };
  989. }
  990.  
  991. /*______________________________________________________________________
  992.  
  993.      utl_GetVolFilCnt - Get the number of files on a volume.
  994.     
  995.      Entry:     volRefNum = volume reference number of volume.
  996.     
  997.      Exit:        function result = number of files on volume.
  998.     
  999.      For serdver volumes this function always returns 0.
  1000. _____________________________________________________________________*/
  1001.  
  1002.  
  1003. long utl_GetVolFilCnt (short volRefNum)
  1004.  
  1005. {
  1006.      HParamBlockRec      pBlock;         /* param block for PHBGetVInfo */
  1007.     
  1008.      pBlock.volumeParam.ioNamePtr = nil;
  1009.      pBlock.volumeParam.ioVRefNum = volRefNum;
  1010.      pBlock.volumeParam.ioVolIndex = 0;
  1011.      (void) PBHGetVInfo(&pBlock, false);
  1012.      return pBlock.volumeParam.ioVFilCnt;
  1013. }
  1014.  
  1015. /*______________________________________________________________________
  1016.  
  1017.      utl_HaveColor - Determine if system has color QuickDraw.
  1018.  
  1019.      Exit:        function result = true if we have color QD.
  1020. _____________________________________________________________________*/
  1021.  
  1022.  
  1023. Boolean utl_HaveColor (void)
  1024.  
  1025. {
  1026.      if (!GotSysEnviron) GetSysEnvirons();
  1027.      return TheWorld.hasColorQD;
  1028. }
  1029.  
  1030. /*______________________________________________________________________
  1031.  
  1032.      utl_HaveSound - Determine if system has the Sound Manager.
  1033.  
  1034.      Exit:        function result = true if we have sound.
  1035. _____________________________________________________________________*/
  1036.  
  1037.  
  1038. Boolean utl_HaveSound (void)
  1039.  
  1040. {
  1041.      if (!GotSysEnviron) GetSysEnvirons();
  1042.      return (TheWorld.systemVersion >= 0x0602);
  1043. }
  1044.  
  1045. /*______________________________________________________________________
  1046.  
  1047.      utl_InitSpinCursor - Initialize animated cursor.
  1048.     
  1049.      Entry:     cursArray = array of handles to cursors.
  1050.                         numCurs = number of cursors to rotate.
  1051.                         tickInterval = interval between cursor rotations.
  1052. _____________________________________________________________________*/
  1053.  
  1054.  
  1055. void utl_InitSpinCursor (CursHandle *cursArray, short numCurs,
  1056.      short tickInterval)
  1057.  
  1058. {
  1059.      CursHandle         h;
  1060.  
  1061.      CursArray = cursArray;
  1062.      CurCurs = 0;
  1063.      NumCurs = numCurs;
  1064.      TickInterval = tickInterval;
  1065.      LastTick = TickCount();
  1066.      h = *cursArray;
  1067.      SetCursor(*h);
  1068. }
  1069.  
  1070. /*______________________________________________________________________
  1071.  
  1072.      utl_InvalGrow - Invalidate Grow Icon.
  1073.     
  1074.      Entry:                 theWindow = pointer to window.
  1075.     
  1076.      This routine should be called before and after calling SizeWindow
  1077.      for windows with grow icons.
  1078. _____________________________________________________________________*/
  1079.  
  1080.  
  1081. void utl_InvalGrow (WindowPtr theWindow)
  1082.  
  1083. {
  1084.      Rect              r;             /* rect to be invalidated */
  1085.     
  1086.      r = theWindow->portRect;
  1087.      r.top = r.bottom - 15;
  1088.      r.left = r.right - 15;
  1089.      InvalRect(&r);
  1090. };
  1091.  
  1092. /*______________________________________________________________________
  1093.  
  1094.      utl_IsDAWindow - Check to see if a window is a DA.
  1095.     
  1096.      Entry:     theWindow = pointer to dialog window.
  1097.                         
  1098.     
  1099.      Exit:        function result = true if DA window.
  1100. _____________________________________________________________________*/
  1101.  
  1102.  
  1103. Boolean utl_IsDAWindow (WindowPtr theWindow)
  1104.  
  1105. {
  1106.      return ((WindowPeek)theWindow)->windowKind < 0;
  1107. }
  1108.  
  1109. /*______________________________________________________________________
  1110.  
  1111.      utl_IsLaser - Check Printer for LaserWriter.
  1112.     
  1113.      Entry:     hPrint = handle to print record.
  1114.     
  1115.      Exit:        function result = true if LaserWriter.
  1116.     
  1117. _____________________________________________________________________*/
  1118.  
  1119.  
  1120. Boolean utl_IsLaser (THPrint hPrint)
  1121.  
  1122. {
  1123.      unsigned char    wDev;                  /* printer device */
  1124.  
  1125.      wDev = (**hPrint).prStl.wDev >> 8;
  1126.      return wDev==3 || wDev==4;
  1127. }
  1128.  
  1129. /*______________________________________________________________________
  1130.  
  1131.      utl_LockControls - Lock Window Controls
  1132.     
  1133.      Entry:     theWindow = pointer to window.
  1134.     
  1135.      This routine moves all the control records in a window high and
  1136.      locks them.    It should be called immediately after creating a new
  1137.      window, and before drawing it.  It works around errors in the Control
  1138.      Manager which showed up when I was testing with TMON's heap scramble and
  1139.      purge option.
  1140. _____________________________________________________________________*/
  1141.  
  1142.  
  1143. void utl_LockControls (WindowPtr theWindow)
  1144.  
  1145. {
  1146.      ControlHandle         theControl;        /* handle to control */
  1147.  
  1148.      theControl = ((WindowPeek)theWindow)->controlList;
  1149.      while (theControl) {
  1150.             MoveHHi((Handle)theControl);
  1151.             HLock((Handle)theControl);
  1152.             theControl = (**theControl).nextControl;
  1153.      };
  1154. }
  1155.  
  1156. /*______________________________________________________________________
  1157.  
  1158.      utl_PlotSmallIcon - Draw a small icon.
  1159.     
  1160.      Entry:     theRect = rectangle in which to draw the small icon.
  1161.                         theHandle = handle to small icon.
  1162.                             
  1163.      For best results, the rectangle should be exactly 16 pixels square.
  1164. _____________________________________________________________________*/
  1165.  
  1166.  
  1167. void utl_PlotSmallIcon (Rect *theRect, Handle theHandle)
  1168.  
  1169. {
  1170.      BitMap          srcBits;             /* Source bitmap for CopyBits */
  1171.     
  1172.      MoveHHi(theHandle);
  1173.      HLock(theHandle);
  1174.      srcBits.baseAddr = *theHandle;
  1175.      srcBits.rowBytes = 2;
  1176.      SetRect(&srcBits.bounds, 0, 0, 16, 16);
  1177.      CopyBits(&srcBits, &qd.thePort->portBits, &srcBits.bounds, theRect,
  1178.             srcCopy, nil);
  1179.      HUnlock(theHandle);
  1180. }
  1181.  
  1182. /*______________________________________________________________________
  1183.  
  1184.      utl_PlugParams - Plug parameters into message.
  1185.     
  1186.      Entry:     line1 = input line.
  1187.                         p0, p1, p2, p3 = parameters.
  1188.                             
  1189.      Exit:        line2 = output line.
  1190.                             
  1191.      This routine works just like the toolbox routine ParamText.
  1192.      The input line may contain place-holders ^0, ^1, ^2, and ^3, 
  1193.      which are replaced by the parameters p0-p3.    The input line
  1194.      must not contain any other ^ characters.  The input and output lines
  1195.      may not be the same string.    Pass nil for parameters which don't
  1196.      occur in line1.    If the output line exceeds 255 characters it's
  1197.      truncated.
  1198. _____________________________________________________________________*/
  1199.  
  1200.  
  1201. void utl_PlugParams (Str255 line1, Str255 line2, Str255 p0, 
  1202.      Str255 p1, Str255 p2, Str255 p3)
  1203.  
  1204. {
  1205.      char                     *in;                /* pointer to cur pos in input line */
  1206.      char                     *out;             /* pointer to cur pos in output line */
  1207.      char                     *inEnd;         /* pointer to end of input line */
  1208.      char                     *outEnd;        /* pointer to end of output line */
  1209.      char                     *param;         /* pointer to param to be plugged */
  1210.      short                    len;                /* length of param */
  1211.     
  1212.      in = line1+1;
  1213.      out = line2+1;
  1214.      inEnd = line1 + 1 + *line1;
  1215.      outEnd = line2 + 256;
  1216.      while (in < inEnd ) {
  1217.             if (*in == '^') {
  1218.                  in++;
  1219.                  if (in >= inEnd) break;
  1220.                  switch (*in++) {
  1221.                         case '0':
  1222.                              param = p0;
  1223.                              break;
  1224.                         case '1':
  1225.                              param = p1;
  1226.                              break;
  1227.                         case '2':
  1228.                              param = p2;
  1229.                              break;
  1230.                         case '3':
  1231.                              param = p3;
  1232.                              break;
  1233.                         default:
  1234.                              continue;
  1235.                  };
  1236.                  if (!param) continue;
  1237.                  len = *param;
  1238.                  if (out + len > outEnd) len = outEnd - out;
  1239.                  memcpy(out, param+1, len);
  1240.                  out += len;
  1241.             } else {
  1242.                  if (out >= outEnd) break;
  1243.                  *out++ = *in++;
  1244.             };
  1245.      };
  1246.      *line2 = out - (line2+1);
  1247. };
  1248.  
  1249. /*______________________________________________________________________
  1250.  
  1251.      utl_RestoreWindowPos - Restore Window Position.
  1252.     
  1253.      Entry:     theWindow = pointer to window.
  1254.                         userState = saved user state rectangle for the window.
  1255.                         zoomed = true if window in zoomed state when saved.
  1256.                         offset = pixel offset used in DragRect calls.
  1257.                         computeStdState = pointer to function to compute standard state.
  1258.                         computeDefState = pointer to function to compute default state.
  1259.     
  1260.      Exit:        window position, size, and zoom state restored.
  1261.                         userState = new user state.
  1262.                         
  1263.      See HIN 6: "When reopening a movable window, check its saved 
  1264.      position.    If the window is in a position to which the user could
  1265.      have dragged it, then leave it there.    If the window can be zoomed
  1266.      and was in the zoomed state when it was last closed, put it in the
  1267.      zoomed state again.    (Note that the current and previous zoomed states
  1268.      are not necessarily the same, since the window may be reopened on a
  1269.      different monitor.)    If the window is not in a position to which the
  1270.      user could have dragged it, then it must be relocated, so use the
  1271.      default location.    However, do not automatically use the default size
  1272.      when using the default location; if the entire window would be visible
  1273.      using the default location and stored size, then use the stored size."
  1274.     
  1275.      The "offset" parameter is usually 4.  When initializing the boundary rectangle
  1276.      for DragWindow calls, normally the boundary rectangle of the desktop gray
  1277.      region is inset by 4 pixels.  If some value other than 4 is used, it should
  1278.      be passed to RestoreWindowPos as the "offset" parameter.
  1279.     
  1280.      The computeStdState function is passed a pointer to the window.    Given
  1281.      the userState in the window zoom info, it must compute the standard
  1282.      (zoom) state in the window zoom info.    This is an application-dependent
  1283.      function.
  1284.     
  1285.      The computeDefState function must determine the default position and
  1286.      size of a new window, and return the result as a rectangle.    This may
  1287.      involve invocation of a staggering algorithm or some other algorithm.
  1288.      This is an application-dependent function.
  1289.     
  1290.      Changed to keep window smaller than the desktop's bounding box.
  1291.      (s-dorner@uiuc.edu, 12/16/91)
  1292. _____________________________________________________________________*/
  1293.  
  1294.  
  1295. void utl_RestoreWindowPos (WindowPtr theWindow, Rect *userState,
  1296.      Boolean zoomed, short offset,
  1297.      utl_ComputeStdStatePtr computeStdState,
  1298.      utl_ComputeDefStatePtr computeDefState)
  1299.  
  1300. {
  1301.      WindowPeek         w;                         /* window pointer */
  1302.      short                    userHeight;      /* height of userState */
  1303.      short                    userWidth;         /* width of userState */
  1304.      Rect                     r;                         /* scratch rectangle */
  1305.      RgnHandle            rgn;                     /* scratch region */
  1306.      Rect                     stdState;          /* standard state */
  1307.      short                    windHeight;      /* window height */
  1308.      short                    windWidth;         /* window width */
  1309.  
  1310.      w = (WindowPeek)theWindow;
  1311.      SanitizeSize(userState);
  1312.      if (!utl_CouldDrag(userState, offset)) {
  1313.             userHeight = userState->bottom - userState->top;
  1314.             userWidth = userState->right - userState->left;
  1315.             (*computeDefState)(theWindow, userState);
  1316.             if (!zoomed) {
  1317.                  r = *userState;
  1318.                  r.bottom = r.top + userHeight;
  1319.                  r.right = r.left + userWidth;
  1320.                  r.top -= titleBarHeight;
  1321.                  InsetRect(&r, -1, -1);
  1322.                  rgn = NewRgn();
  1323.                  RectRgn(rgn, &r);
  1324.                  DiffRgn(rgn, *(RgnHandle*)GrayRgn, rgn);
  1325.                  if (EmptyRgn(rgn)) {
  1326.                         userState->bottom = userState->top + userHeight;
  1327.                         userState->right = userState->left + userWidth;
  1328.                  };
  1329.                  DisposeRgn(rgn);
  1330.             };
  1331.      };
  1332.      MoveWindow(theWindow, userState->left, userState->top, false);
  1333.      windHeight = userState->bottom - userState->top;
  1334.      windWidth = userState->right - userState->left;
  1335.      SizeWindow(theWindow, windWidth, windHeight, true);
  1336.      if (w->dataHandle && w->spareFlag) {
  1337.             (**((WStateData**)w->dataHandle)).userState = *userState;
  1338.             (*computeStdState)(theWindow);
  1339.             if (zoomed) {
  1340.                  stdState = (**((WStateData**)w->dataHandle)).stdState;
  1341.                  MoveWindow(theWindow, stdState.left, stdState.top, false);
  1342.                  windHeight = stdState.bottom - stdState.top;
  1343.                  windWidth = stdState.right - stdState.left;
  1344.                  SizeWindow(theWindow, windWidth, windHeight, true);
  1345.             };
  1346.      };
  1347. }
  1348.  
  1349. /*______________________________________________________________________
  1350.  
  1351.      utl_Rom64 - Check to see if we have the old 64K ROM.
  1352.     
  1353.      Exit:        function result = true if 64K ROM.
  1354. _____________________________________________________________________*/
  1355.  
  1356.  
  1357. Boolean utl_Rom64 (void)
  1358.  
  1359. {
  1360.      return *(short*)ROM85 < 0;
  1361. }
  1362.  
  1363. /*______________________________________________________________________
  1364.  
  1365.      utl_RFSanity - Check a Resource File's Sanity.
  1366.     
  1367.      Entry:     *fName = file name.
  1368.     
  1369.      Exit:        *sane = true if resource fork is sane.
  1370.                         function result = error code.
  1371.                         
  1372.      This routine checks the sanity of a resource file.  The Resource Manager
  1373.      does not do error checking, and can bomb or hang if you use it to open
  1374.      a damaged resource file.  This routine can be called first to precheck
  1375.      the file.
  1376.     
  1377.      The routine checks the entire resource map.
  1378.     
  1379.      It is the caller's responsibility to set the proper default volume and
  1380.      directory.
  1381. _____________________________________________________________________*/
  1382.  
  1383.  
  1384. OSErr utl_RFSanity (Str255 fName, Boolean *sane)
  1385.  
  1386. {
  1387.      ParamBlockRec         fBlock;                /* file param block */
  1388.      short                         refNum;                /* file refnum */
  1389.      long                          count;                 /* number of bytes to read */
  1390.      long                          logEOF;                /* logical EOF */
  1391.      Ptr                             map;                     /* pointer to resource map */
  1392.      unsigned long         dataLWA;             /* offset in file of data end */
  1393.      unsigned long         mapLWA;                /* offset in file of map end */
  1394.      unsigned short      typeFWA;             /* offset from map begin to type list */
  1395.      unsigned short      nameFWA;             /* offset from map begin to name list */
  1396.      unsigned char         *pType;                /* pointer into type list */
  1397.      unsigned char         *pName;                /* pointer to start of name list */
  1398.      unsigned char         *pMapEnd;            /* pointer to end of map */
  1399.      short                         nType;                 /* number of resource types in map */
  1400.      unsigned char         *pTypeEnd;         /* pointer to end of type list */
  1401.      short                         nRes;                    /* number of resources of given type */
  1402.      unsigned short      refFWA;                /* offset from type list to ref list */
  1403.      unsigned char         *pRef;                 /* pointer into reference list */
  1404.      unsigned char         *pRefEnd;            /* pointer to end of reference list */
  1405.      unsigned short      resNameFWA;        /* offset from name list to resource name */
  1406.      unsigned char         *pResName;         /* pointer to resource name */
  1407.      unsigned long         resDataFWA;        /* offset from data begin to resource data */
  1408.      Boolean                     mapOK;                 /* true if map is sane */
  1409.      OSErr                         rCode;                 /* error code */
  1410.     
  1411.      struct {
  1412.             unsigned long         dataFWA;        /* offset in file of data */
  1413.             unsigned long         mapFWA;         /* offset in file of map */
  1414.             unsigned long         dataLen;        /* data area length */
  1415.             unsigned long         mapLen;         /* map area length */
  1416.      } header;
  1417.     
  1418.      /* Open the resource file. */
  1419.     
  1420.      fBlock.ioParam.ioNamePtr = fName;
  1421.      fBlock.ioParam.ioVRefNum = 0;
  1422.      fBlock.ioParam.ioVersNum = 0;
  1423.      fBlock.ioParam.ioPermssn = fsRdPerm;
  1424.      fBlock.ioParam.ioMisc = nil;
  1425.      if (rCode = PBOpenRF(&fBlock, false)) {
  1426.             if (rCode == fnfErr) {
  1427.                  *sane = true;
  1428.                  return noErr;
  1429.             } else {
  1430.                  return rCode;
  1431.             };
  1432.      };
  1433.     
  1434.      /* Get the logical eof of the file. */
  1435.     
  1436.      refNum = fBlock.ioParam.ioRefNum;
  1437.      if (rCode = GetEOF(refNum, &logEOF)) return rCode;
  1438.      if (!logEOF) {
  1439.             *sane = true;
  1440.             if (rCode = FSClose(refNum)) return rCode;
  1441.             return noErr;
  1442.      };
  1443.     
  1444.      /* Read and validate the resource header. */
  1445.     
  1446.      count = 16;
  1447.      if (rCode = FSRead(refNum, &count, (Ptr)&header)) {
  1448.             FSClose(refNum);
  1449.             return rCode;
  1450.      };
  1451.      dataLWA = header.dataFWA + header.dataLen;
  1452.      mapLWA = header.mapFWA + header.mapLen;
  1453.      mapOK = count == 16 && header.mapLen > 28 &&
  1454.             header.dataFWA < 0x01000000 && header.mapFWA < 0x01000000 &&
  1455.             dataLWA <= logEOF && mapLWA <= logEOF &&
  1456.             (dataLWA <= header.mapFWA || mapLWA <= header.dataFWA);
  1457.             
  1458.      /* Read the resource map. */
  1459.     
  1460.      map = nil;
  1461.      if (mapOK) {
  1462.             map = NuPtr(header.mapLen);
  1463.             if (!(rCode = SetFPos(refNum, fsFromStart, header.mapFWA))) {
  1464.                  count = header.mapLen;
  1465.                  rCode = FSRead(refNum, &count, map);
  1466.             };
  1467.      };
  1468.     
  1469.      /* Verify the type list and name list offsets. */
  1470.     
  1471.      if (!rCode) {
  1472.             typeFWA = *(unsigned short*)(map+24);
  1473.             nameFWA = *(unsigned short*)(map+26);
  1474.             mapOK = typeFWA == 28 && nameFWA >= typeFWA && nameFWA <= header.mapLen &&
  1475.                  !(typeFWA & 1) && !(nameFWA & 1);
  1476.      };
  1477.     
  1478.      /* Verify the type list, reference lists, and name list. */
  1479.     
  1480.      if (mapOK) {
  1481.             pType = map + typeFWA;
  1482.             pName = map + nameFWA;
  1483.             pMapEnd = map + header.mapLen;
  1484.             nType = *(short*)pType + 1;
  1485.             pType += 2;
  1486.             pTypeEnd = pType + (nType<<3);
  1487.             if (mapOK = pTypeEnd <= pMapEnd) {
  1488.                  while (pType < pTypeEnd) {
  1489.                         nRes = *(short*)(pType+4) + 1;
  1490.                         refFWA = *(unsigned short*)(pType+6);
  1491.                         pRef = map + typeFWA + refFWA;
  1492.                         pRefEnd = pRef + 12*nRes;
  1493.                         if (!(mapOK = pRef >= pTypeEnd && pRef < pName && 
  1494.                              !(refFWA & 1))) break;
  1495.                         while (pRef < pRefEnd) {
  1496.                              resNameFWA = *(unsigned short*)(pRef+2);
  1497.                              if (resNameFWA != 0xFFFF) {
  1498.                                     pResName = pName + resNameFWA;
  1499.                                     if (!(mapOK = pResName + *pResName < pMapEnd)) break;
  1500.                              };
  1501.                              resDataFWA = *(unsigned long*)(pRef+4) & 0x00FFFFFF;
  1502.                              if (!(mapOK = header.dataFWA + resDataFWA < dataLWA)) break;
  1503.                              pRef += 12;
  1504.                         };
  1505.                         if (!mapOK) break;
  1506.                         pType += 8;
  1507.                  };
  1508.             };
  1509.      };
  1510.     
  1511.      /* Dispose of the resource map, close the file and return. */
  1512.     
  1513.      if (map) DisposPtr(map);
  1514.      if (!rCode) {
  1515.             rCode = FSClose(refNum);
  1516.      } else {
  1517.             (void) FSClose(refNum);
  1518.      };
  1519.      *sane = mapOK;
  1520.      return rCode;
  1521. }
  1522.  
  1523. /*______________________________________________________________________
  1524.  
  1525.      utl_SaveWindowPos - Save Window Position.
  1526.     
  1527.      Entry:     theWindow = window pointer.
  1528.     
  1529.      Exit:        userState = user state rectangle of the window.
  1530.                         zoomed = true if window zoomed.
  1531.                         
  1532.      See HIN 6: "Before closing a movable window, check to see if its
  1533.      location or size have changed.  If so, save the new location and
  1534.      size.    If the window can be zoomed, save the user state and also 
  1535.      save whether or not the window is in the zoomed (standard) sate."
  1536.     
  1537.      We assume in this routine that the caller has already kept track
  1538.      of the fact that this window's location or size has changed, and that
  1539.      we do indeed need to save the location and size.
  1540.     
  1541.      This routine only works if the window's origin has not been offset.
  1542. _____________________________________________________________________*/
  1543.  
  1544.  
  1545. void utl_SaveWindowPos (WindowPtr theWindow, Rect *userState, Boolean *zoomed)
  1546.  
  1547. {
  1548.      GrafPtr         savedPort;         /* saved grafport */
  1549.      WindowPeek  w;                         /* window pointer */
  1550.      Rect              curState;            /* current window rect, global coords */
  1551.      Rect              stdState;            /* standard (zoom) rect, global coords */
  1552.      Point             p;                         /* scratch point */
  1553.      Rect              r;                         /* scratch rect */
  1554.     
  1555.      GetPort(&savedPort);
  1556.      SetPort(theWindow);
  1557.      SetPt(&p, 0, 0);
  1558.      LocalToGlobal(&p);
  1559.      curState = theWindow->portRect;
  1560.      OffsetRect(&curState, p.h, p.v);
  1561.      w = (WindowPeek)theWindow;
  1562.      if (w->dataHandle && w->spareFlag) {
  1563.             /* This window supports zooming */
  1564.             /* Determine if window is zoomed.  The criteria is that both the
  1565.                  top left and bottom right corners of the current window rectangle
  1566.                  and the standard (zoom) rectangle must be within 7 pixels of each
  1567.                  other.  This is the same algorithm as the one used by the standard
  1568.                  system window definition function. */
  1569.             *zoomed = false;
  1570.             stdState = (**((WStateData**)w->dataHandle)).stdState;
  1571.             SetPt(&p, curState.left, curState.top);
  1572.             SetRect(&r, stdState.left, stdState.top, stdState.left, stdState.top);
  1573.             InsetRect(&r, -7, -7);
  1574.             if (PtInRect(p, &r)) {
  1575.                  SetPt(&p, curState.right, curState.bottom);
  1576.                  SetRect(&r, stdState.right, stdState.bottom, stdState.right,
  1577.                         stdState.bottom);
  1578.                  InsetRect(&r, -7, -7);
  1579.                  *zoomed = PtInRect(p, &r);
  1580.             };
  1581.             if (*zoomed) {
  1582.                  *userState = (**((WStateData**)w->dataHandle)).userState;
  1583.             } else {
  1584.                  *userState = curState;
  1585.             };
  1586.      } else {
  1587.             /* This window does not support zooming. */
  1588.             *zoomed = false;
  1589.             *userState = curState;
  1590.      };
  1591.      SetPort(savedPort);
  1592. }
  1593.  
  1594. /*______________________________________________________________________
  1595.  
  1596.      utl_ScaleFontSize - Scale Font Size
  1597.     
  1598.      Entry:     fontNum = font number.
  1599.                         fontSize = nominal font size.
  1600.                         percent = percent change in size.
  1601.                         laser = true if laserwriter.
  1602.     
  1603.      Exit:        function result = scaled font size.
  1604.                         
  1605.      The nominal font size is multiplied by the percentage,
  1606.      then truncated.    For non-laserwriters it is then rounded down
  1607.      to the nearest font size which is available in that true size,
  1608.      without font manager scaling, or which can be generated by doubling
  1609.      an existing font size.
  1610. _____________________________________________________________________*/
  1611.  
  1612.  
  1613. short utl_ScaleFontSize (short fontNum, short fontSize, short percent,
  1614.      Boolean laser)
  1615.     
  1616. {
  1617.      short             nSize;                      /* new size */
  1618.      short             x;                              /* new test size */
  1619.     
  1620.      nSize = fontSize * percent / 100;
  1621.      if (!laser) {
  1622.             x = nSize;
  1623.             while (x > 0) {
  1624.                  if (RealFont(fontNum, x)) break;
  1625.                  if (!(x&1) && RealFont(fontNum, x>>1)) break;
  1626.                  x--;
  1627.             };
  1628.             if (x) nSize = x;
  1629.      };
  1630.      return nSize;
  1631. }
  1632.  
  1633. /*______________________________________________________________________
  1634.  
  1635.      utl_SpinCursor - Animate cursor.
  1636.     
  1637.      After calling InitSpinCursor to initialize an animated cursor, call
  1638.      SpinCursor periodically to make the cursor animate.
  1639. _____________________________________________________________________*/
  1640.  
  1641.  
  1642. void utl_SpinCursor (void)
  1643.  
  1644. {
  1645.      CursHandle         h;                    /* handle to cursor */
  1646.      long                     ticksNow;     /* current tick count */
  1647.     
  1648.      ticksNow = TickCount();
  1649.      if (ticksNow < LastTick + TickInterval) return;
  1650.      LastTick = ticksNow;
  1651.      CurCurs++;
  1652.      if (CurCurs >= NumCurs) CurCurs = 0;
  1653.      h = CursArray[CurCurs];
  1654.      SetCursor(*h);
  1655. }
  1656.  
  1657. /*______________________________________________________________________
  1658.  
  1659.      utl_StaggerWindow - Stagger a New Window
  1660.     
  1661.      Entry:     windRect = window portrect.
  1662.                         initialOffset = intitial pixel offset of window from corner.
  1663.                         offset = offset for subsequent staggered windows.
  1664.     
  1665.      Exit:        pos = window position.
  1666.     
  1667.      According to HIN 6, a new window should be positioned as follows:
  1668.      "The first document window should be positioned in the upper-left corner
  1669.      of the gray area of the main screen (the screen with the menu bar).
  1670.      Each additional independent window should be staggered from the upper-left
  1671.      corner of the screen that contains the largest portion of the
  1672.      frontmost window."  Also, "When a window is used or closed, its original
  1673.      position becomes available again.    The next window opened should use this
  1674.      position.    Similarly, if a window is moved onto a previously available
  1675.      position, that position becomes unavailable again."
  1676.     
  1677.      This routine implements these rules.  A position is considered to be
  1678.      "unavailable" if some other window is within (offset+1)/2 pixels of the
  1679.      position in both the vertical and horizontal directions.
  1680.     
  1681.      If all slots are occupied, the routine attempts to locate the first one
  1682.      which is occupied by only one other window.    If this attempt fails, it
  1683.      tries to locate one which is occupied by only two other windows, etc.
  1684.      Thus, if the screen is filled with staggered windows, subsequent windows
  1685.      will be staggered on top of the existing ones, forming a second "layer."
  1686.      If this layer fills up, a third layer is started, etc.
  1687.     
  1688.      Steve Dorner, UIUC Computing Services Office 9/27/90
  1689.      Invisible windows are no longer considered by the function.
  1690.      Horizontal offset is 2 pixels on small screens
  1691.      Steve Dorner, UIUC Computing Services Office 3/92
  1692.      Leaving 2 pixel margin at screen bottom to allow for autoscroll
  1693.      Added optional insets
  1694.      Steve Dorner, UIUC Computing Services Office 4/92
  1695.      Added parameter for specifying a particular device
  1696. _____________________________________________________________________*/
  1697.  
  1698. #define SIZE_9    540         /* a 9" (or so) screen */               /* sd */
  1699. #define OFF_9     3             /* horizontal offset for 9" screen */   /* sd */
  1700. void utl_StaggerWindow (Rect *windRect, short initialOffset, short offset,
  1701.      Point *pos,short specificDevice)
  1702.  
  1703. {
  1704.      GrafPtr                savedPort;         /* saved grafport */
  1705.      short                    offsetDiv2;      /* offset/2 */
  1706.      short                    windHeight;      /* window height */
  1707.      short                    windWidth;         /* window width */
  1708.      WindowPtr            frontWind;         /* pointer to front window */
  1709.      GDHandle             gd;                      /* GDevice */
  1710.      Rect                     screenRect;      /* screen rectangle */
  1711.      Rect                     junkRect;          /* window rectangle */
  1712.      Boolean                hasMB;                 /* true if screen has menu bar */
  1713.      Point                    initPos;             /* initial staggered window position */
  1714.      Point                    curPos;              /* current staggered window position */
  1715.      WindowPtr            curWind;             /* pointer to current window */
  1716.      Point                    windPos;             /* current window position */
  1717.      short                    deltaH;              /* horizontal distance */
  1718.      short                    deltaV;              /* vertical distance */
  1719.      short                    layer;                 /* layer number */
  1720.      short                    nOccupied;         /* number windows occupying cur pos */
  1721.      Boolean                noPos;                 /* true if no position is on screen */
  1722.      Boolean                is9;                     /* is this a 9" screen? */     /* sd */
  1723.     
  1724.      GetPort(&savedPort);
  1725.      offsetDiv2 = (offset+1)>>1;
  1726.      windHeight = windRect->bottom - windRect->top;
  1727.      windWidth = windRect->right - windRect->left;
  1728.      frontWind = FrontWindow();
  1729.      if (specificDevice) {
  1730.             utl_GetIndGD(specificDevice,&gd,&screenRect,&hasMB);
  1731.      } else if (frontWind) {
  1732.             utl_GetWindGD(frontWind, &gd, &screenRect, &junkRect, &hasMB);
  1733.      } else {
  1734.             screenRect = qd.screenBits.bounds;
  1735.             hasMB = true;
  1736.      };
  1737.      if (hasMB) screenRect.top += utl_GetMBarHeight();
  1738.      screenRect.bottom -= 2;                                                                            /* sd */
  1739.      screenRect.left += GetRLong(DESK_LEFT_STRIP);                                /* sd */
  1740.      screenRect.right -= GetRLong(DESK_RIGHT_STRIP);                            /* sd */
  1741.      screenRect.bottom -= GetRLong(DESK_BOTTOM_STRIP);                        /* sd */
  1742.      screenRect.top += GetRLong(DESK_TOP_STRIP);                                    /* sd */
  1743.      SetPt(&initPos, screenRect.left + initialOffset + 1, 
  1744.             screenRect.top + initialOffset + titleBarHeight);
  1745.      is9 = screenRect.right-screenRect.left<=SIZE_9;                            /* sd */
  1746.      layer = 1;
  1747.      while (true) {
  1748.             /* Test each layer number "layer", starting with 1 and incrementing by 1.
  1749.                  Break out of the loop when we find a position curPos which
  1750.                  is "occupied" by fewer than "layer" other windows. */
  1751.             curPos = initPos;
  1752.             noPos = true;
  1753.             while (true) {
  1754.                  /* Test each possible position curPos.  Break out of the loop
  1755.                         when we have exhaused the possible positions, or when we
  1756.                         have located one which has < layer "occupants". */
  1757.                  curWind = frontWind;
  1758. #ifndef NEWWAY
  1759.                     if (curPos.v + windHeight >= screenRect.bottom ||
  1760.                         curPos.h + windWidth >= screenRect.right) {
  1761.                         break;
  1762.                  };
  1763. #else
  1764.                     if (curPos.h + windWidth >= screenRect.right) break;
  1765.                      if (curPos.v + windHeight >= screenRect.bottom) curPos.v = initPos.v;
  1766. #endif
  1767.                  noPos = false;
  1768.                  nOccupied = 0;
  1769.                  while (curWind) {
  1770.                         /* Scan the window list and count up how many of them "occupy"
  1771.                              the current location curPos.  Break out of the loop when
  1772.                              we reach the end of the list, or when the count is >=
  1773.                              layer. */
  1774.                         if (((WindowPeek)curWind)->visible) {                             /* sd */
  1775.                              SetPt(&windPos, 0, 0);
  1776.                              SetPort(curWind);
  1777.                              LocalToGlobal(&windPos);
  1778.                              deltaH = curPos.h - windPos.h;
  1779.                              deltaV = curPos.v - windPos.v;
  1780.                              if (deltaH < 0) deltaH = -deltaH;
  1781.                              if (deltaV < 0) deltaV = -deltaV;
  1782.                              if (deltaH <= offsetDiv2 && deltaV <= offsetDiv2) {
  1783.                                     nOccupied++;
  1784.                                     if (nOccupied >= layer) break;
  1785.                              };
  1786.                         };                                                                                                    /* sd */
  1787.                         curWind = (WindowPtr)(((WindowPeek)curWind)->nextWindow);
  1788.                  };
  1789.                  if (!curWind) break;
  1790.                  curPos.h += is9 ? OFF_9 : offset;
  1791.                  curPos.v += offset;
  1792.             };
  1793.             if (!curWind || noPos) break;
  1794.             layer++;
  1795.      };
  1796.      SetPort(savedPort);
  1797.    *pos = curPos;
  1798. }
  1799.  
  1800. /*______________________________________________________________________
  1801.  
  1802.      CancelFilter - Command Period Dialog Filter Proc.
  1803.     
  1804.      Entry:     theDialog = pointer to dialog record.
  1805.                         theEvent = pointer to event record.
  1806.     
  1807.      Exit:        if command-period or escape typed:
  1808.     
  1809.                         function result = true.
  1810.                         itemHit = item number of cancel button.
  1811.                         
  1812.                         else if user specified a filterProc on the call to
  1813.                         utl_StopAlert:
  1814.                         
  1815.                         user's filterProc called, function result and itemHit
  1816.                         returned by user's filterProc.
  1817.                         
  1818.                         else:
  1819.                         
  1820.                         function result = false.
  1821.                         itemHit = undefined.
  1822. _____________________________________________________________________*/
  1823.  
  1824.  
  1825. static pascal Boolean CancelFilter (DialogPtr theDialog,
  1826.      EventRecord *theEvent, short *itemHit)
  1827.     
  1828. {
  1829.      short                    key;                /* ascii code of key pressed */
  1830.     
  1831.      if (theEvent->what != keyDown && theEvent->what != autoKey) {
  1832.             if (Filter) {
  1833.                  return (*Filter)(theDialog, theEvent, itemHit);
  1834.             } else {
  1835.                  return false;
  1836.             };
  1837.      } else {
  1838.             key = theEvent->message & charCodeMask;
  1839.             if (key == escapeKey) {
  1840.                  *itemHit = CancelItem;
  1841.                  utl_FlashButton(theDialog, CancelItem);
  1842.                  return true;
  1843.             } else if ((theEvent->modifiers & cmdKey) &&
  1844.                  (key == '.')) {
  1845.                  *itemHit = CancelItem;
  1846.                  utl_FlashButton(theDialog, CancelItem);
  1847.                  return true;
  1848.             } else if (Filter) {
  1849.                  return (*Filter)(theDialog, theEvent, itemHit);
  1850.             } else if (key == returnKey || key==enterKey) {
  1851.                  *itemHit = 1;
  1852.                  utl_FlashButton(theDialog, 1);
  1853.                  return true;
  1854.             } else {
  1855.                  return false;
  1856.             };
  1857.      };
  1858. }
  1859.  
  1860. /*______________________________________________________________________
  1861.  
  1862.      utl_StopAlert - Present Stop Alert
  1863.     
  1864.      Entry:     alertID = resource id of alert.
  1865.                         filterProc = pointer to filter proc.
  1866.                         cancelItem = item number of cancel button, or 0 if
  1867.                              none.
  1868.     
  1869.      Exit:        function result = item number
  1870.                         
  1871.      This routine is identical to the Dialog Manager routine StopAlert,
  1872.      except that it centers the alert on the main window, and if requested,
  1873.      command/period or the Escape key is treated the same as a click on the 
  1874.      Cancel button.
  1875. _____________________________________________________________________*/
  1876.  
  1877.  
  1878. short utl_StopAlert (short alertID, ModalFilterProcPtr filterProc,
  1879.      short cancelItem)
  1880.  
  1881. {
  1882.      Handle                 h;                    /* handle to alert resource */
  1883.      short                    result;         /* function result */
  1884.     
  1885.      h = GetResource('ALRT', alertID);
  1886.      HLock(h);
  1887.      utl_CenterDlogRect(*(Rect**)h, false);
  1888.      if (cancelItem) {
  1889.             Filter = filterProc;
  1890.             CancelItem = cancelItem;
  1891.             result = StopAlert(alertID, CancelFilter);
  1892.      } else {
  1893.             result = StopAlert(alertID, filterProc);
  1894.      };
  1895.      HUnlock(h);
  1896.      return result;
  1897. }
  1898.  
  1899. /*______________________________________________________________________
  1900.  
  1901.      utl_SysHasNotMgr - Check to See if System has Notification Manager.
  1902.     
  1903.      Exit:             function result = true if system has Notification
  1904.                                     Manager..
  1905.     
  1906.      The system version must be >= 6.0.
  1907. _____________________________________________________________________*/
  1908.  
  1909.  
  1910. Boolean utl_SysHasNotMgr (void)
  1911.  
  1912. {
  1913.      if (!GotSysEnviron) GetSysEnvirons();
  1914.      return TheWorld.systemVersion >= 0x0600;
  1915. }
  1916.  
  1917. /*______________________________________________________________________
  1918.  
  1919.      utl_SysHasPopUp - Check to See if System has Popup Menus.
  1920.     
  1921.      Exit:             function result = true if system has popup menus.
  1922.     
  1923.      The system version must be >= 4.1, the machine must have the 128 ROM or
  1924.      later, and the PopUpMenuSelect trap must exist.
  1925. _____________________________________________________________________*/
  1926.  
  1927.  
  1928. Boolean utl_SysHasPopUp (void)
  1929.  
  1930. {
  1931.      if (!GotSysEnviron) GetSysEnvirons();
  1932.      if ((TheWorld.systemVersion < 0x0410) || (TheWorld.machineType == envMac)) {
  1933.             return false;
  1934.      } else {
  1935.             return NGetTrapAddress(_PopUpMenuSelect & 0x3ff, ToolTrap) !=
  1936.                  NGetTrapAddress(_Unimplemented & 0x3ff, ToolTrap);
  1937.      };
  1938. }
  1939.  
  1940. /*______________________________________________________________________
  1941.  
  1942.      utl_VolIsMFS - Test for MFS volume.
  1943.     
  1944.      Entry:     vRefNum = volume reference number.
  1945.     
  1946.      Exit:        function result = true if volume is MFS.
  1947. _____________________________________________________________________*/
  1948.  
  1949.  
  1950. Boolean utl_VolIsMFS (short vRefNum)
  1951.  
  1952. {
  1953.      HParamBlockRec      vBlock;                /* vol info param block */
  1954.     
  1955.      vBlock.volumeParam.ioNamePtr = nil;
  1956.      vBlock.volumeParam.ioVolIndex = 0;
  1957.      vBlock.volumeParam.ioVRefNum = vRefNum;
  1958.      vBlock.volumeParam.ioVSigWord = 0xd2d7;        /* in case we don't have HFS */
  1959.      (void) PBHGetVInfo(&vBlock, false);
  1960.      return vBlock.volumeParam.ioVSigWord == 0xd2d7;
  1961. }
  1962.  
  1963. /*______________________________________________________________________
  1964.  
  1965.      utl_WaitNextEvent - Get Next Event.
  1966.     
  1967.      Entry:     eventMask = event mask.
  1968.                         sleep = sleep interval.
  1969.                         mouseRgn = mouse region.
  1970.     
  1971.      Exit:        theEvent = the next event.
  1972.                         function result = true if event to be processed.
  1973.                         
  1974.      This routine calls WaitNextEvent if the trap exists, otherwise it
  1975.      calls GetNextEvent.    
  1976.     
  1977.      If GetNextEvent is called, the sleep and mouseRgn parameters are 
  1978.      ignored.  SystemTask is also called.
  1979.                         
  1980.      This routine also saves and restores the current grafport.  This is
  1981.      necessary to protect against some GetNextEvent trap patches which change
  1982.      the grafport without restoring it (e.g., the Flex screen saver).
  1983. _____________________________________________________________________*/
  1984.  
  1985.  
  1986. Boolean utl_WaitNextEvent (short eventMask, EventRecord *theEvent,
  1987.      long sleep, RgnHandle mouseRgn)
  1988.  
  1989. {
  1990.      GrafPtr                curPort;        /* pointer to current grafport */
  1991.      Boolean                result;         /* function result */
  1992.      static short     wne = 2;        /* 0 if WaitNextEvent does not exist
  1993.                                                                  1 if WaitNextEvent exists
  1994.                                                                  2 if we don't yet know (first call) */
  1995.     
  1996.      /* Find out whether the WaitNextEvent trap is implemented if this is 
  1997.             the first call. */
  1998.     
  1999.      if (wne == 2) {
  2000.             if (!GotSysEnviron) GetSysEnvirons();
  2001.             if (TheWorld.machineType < 0) {
  2002.                  wne = false;
  2003.             } else {
  2004.                  wne = (NGetTrapAddress(_WaitNextEvent & 0x3ff, ToolTrap) ==
  2005.                         NGetTrapAddress(_Unimplemented & 0x3ff, ToolTrap)) ? 0 : 1;
  2006.             };
  2007.      };
  2008.     
  2009.      /* Save the port, call the trap, and restore the port. */
  2010.     
  2011.      GetPort(&curPort);
  2012.      if (wne) {
  2013.             result = WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
  2014.      } else {
  2015.             SystemTask();
  2016.             result = GetNextEvent(eventMask, theEvent);
  2017.      };
  2018.      SetPort(curPort);
  2019.      return result;
  2020. }
  2021.  
  2022.